<?php

namespace App\Admin\Eloquent;

use Cache;
use App\Exceptions\BusinessException;

class CodeType extends Model
{
	/**
	 * 设置逐渐 id
	 *
	 * @var string
	 */
	protected $primaryKey = 'id';

	/**
     * 设置主键 id 不自增
     *
     * @var bool
     */
    public $incrementing = false;

	/**
     * 实例化模型时, 可批量赋值属性白名单
     *
     * @var array
     */
    protected $fillable = [
        'id', 'name', 'description'
    ];

    /**
     * 代码类别下代码
     * 
     * @return  \App\Admin\Eloquent\Code[]
     */
    public function codes()
    {
        return $this->hasMany('App\Admin\Eloquent\Code', 'type_id', 'id');
    }

    /**
     * 获取代码类别缓存 key
     *
     * @return string
     */
    protected static function getCodeTypesCacheKey()
    {
        return 'cache_code_types';
    }

    /**
     * 缓存所有代码类别
     *
     * @return \App\Admin\Eloquent\CodeType[]
     */
    public static function cachedCodeTypes()
    {
        return Cache::remember(static::getCodeTypesCacheKey(), 60, function () {
            return static::orderBy('created_at', 'desc')->get();
        });
    }

    /**
     * 清空混存代码类别
     *
     * @return void
     */
    public static function clearCachedCodeTypes()
    {
        Cache::forget(static::getCodeTypesCacheKey());
    }

    /**
     * 从缓存的代码类别中查找代码类别
     *
     * @return \App\Admin\Eloquent\CodeType|null
     */
    public static function findFromCachedCodeTypes($codeTypeId)
    {
        foreach (static::cachedCodeTypes() as $cachedCodeType) {
          if ($cachedCodeType->id == $codeTypeId) {
            return $cachedCodeType;
          }
        }

        return null;
    }

    /**
     * 获取代码缓存 key
     *
     * @return string
     */
    protected function getCodesCacheKey()
    {
        $codeTypePrimaryKey = $this->primaryKey;
        return 'cache_codes_for_code_type_'.$this->$codeTypePrimaryKey;
    }

    /**
     * 缓存代码类别下的代码
     *
     * @return \App\Admin\Eloquent\Code[]
     */
    public function cachedCodes()
    {
        if(env('APP_DEBUG', false)){
            return $this->codes()->orderBy('level')->orderBy('sort', 'desc')->get();
        }
        return Cache::remember($this->getCodesCacheKey(), 60, function () {
            return $this->codes()->orderBy('level')->orderBy('sort', 'desc')->get();
        });
    }

    /**
     * 清空缓存
     *
     * @return void
    */
    public function clearCachedCodes()
    {
        Cache::forget($this->getCodesCacheKey());
    }

    /**
   * 保存代码类别修改
   *
   * @param  array $options
   * @return bool|null
   */
  public function save(array $options = [])
  {
    $saved = parent::save($options);

    static::clearCachedCodeTypes();

    return $saved;
  }

  /**
   * 删除代码类别
   *
   * @return bool|null
   */
    public function delete()
    {
        if ($this->hasCodes()) {
            throw new BusinessException('代码类别 ['.$this->id.'] 下不能有代码');
        }

        $deleted = parent::delete();

        static::clearCachedCodeTypes();

        return $deleted;
    }

   /**
    * 是否有代码
    *
    * @return bool
    */
    public function hasCodes()
    {
        if (count($this->codes) > 0) {
            return true;
        }

        return false;
    }

    /**
     * 分页查询
     * 
     * @param  array       $options
     * @param  int|integer $perPage
     * @return \App\Admin\Eloquent\CodeType[]
     */
    public static function paginateQuery(array $options = [], int $perPage = 15)
    {
        $query = static::query();

        if (isset($options['search']) && !empty($options['search'])) {
            $condition = '%'.$options['search'].'%';

            $query = $query->where('id', 'like', $condition)
                        ->orWhere('name', 'like', $condition)
                        ->orWhere('description', 'like', $condition);
        }

        return $query->paginate($perPage);
    }

    /**
     * 分页查询代码
     *
     * @param  array $options
     * @param  int   $perPage
     * @return \App\Admin\Eloquent\Code[]
     */
    public function paginateQueryCodes(array $options = [], int $perPage = 15)
    {
        $query = $this->codes();

        if (isset($options['search']) && empty(!$options['search'])) {
            $condition = '%'.$options['search'].'%';

            $query = $query->where('code', 'like', $condition)
                     ->orWhere('name', 'like', $condition)
                     ->orWhere('parent_code', 'like', $condition)
                     ->orWhere('description', 'like', $condition);
        }

        return $query->orderBy('created_at', 'desc')->paginate($perPage);
    }
}